package openapi

import (
	"context"
	"strings"

	"github.com/starter-go/httpagent"
)

// 定义 RequestHeader（公共请求头）
const (

	// required

	XACSAction        = "x-acs-action"
	XACSVersion       = "x-acs-version"
	XACSDate          = "x-acs-date"
	Host              = "host"
	XACSContentSHA256 = "x-acs-content-sha256"

	// [optional|required] (half)

	Authorization     = "Authorization"
	XACSSecurityToken = "x-acs-security-token"

	// optional

	XACSSignatureNonce = "x-acs-signature-nonce"
)

////////////////////////////////////////////////////////////////////////////////

// Style 是表示 OpenAPI 风格的字符串
type Style string

// 定义 OpenAPI 的风格
const (
	StyleRPC Style = "RPC"
	StyleROA Style = "ROA"
)

////////////////////////////////////////////////////////////////////////////////

// Header ...
type Header struct {
	Name   string
	Values []string
}

// Set 设置 header 的值
func (inst *Header) Set(value string) {
	inst.Values = []string{value}
}

// Add 向 header 添加一个值
func (inst *Header) Add(value string) {
	inst.Values = append(inst.Values, value)
}

// Get ... 获取表示值的字符串，如果有多个值，把他们用 ',' 连起来
func (inst *Header) Get() string {
	b := new(strings.Builder)
	src := inst.Values
	for i, value := range src {
		if i > 0 {
			b.WriteRune(',')
		}
		b.WriteString(value)
	}
	return b.String()
}

////////////////////////////////////////////////////////////////////////////////

// Request 表示一个通用的 aliyun-open-api 请求
type Request struct {
	Context     context.Context
	Task        Task
	Client      Client
	WebRequest  *httpagent.Request  // web 请求
	WebResponse *httpagent.Response // web 响应
	Style       Style               // [RPC|ROA]
	Params      map[string]string   // 调用参数

	// 一个完整的阿里云 OpenAPI 请求，包含以下部分。
	// ResourceURIParameters string

	Protocol        string
	Endpoint        string
	HTTPMethod      string
	Action          string
	APIVersion      string
	PathParameters  []string // ResourceURIParameters.path ；路径中的各项参数
	QueryParameters []string // ResourceURIParameters.query ；查询中的各项参数
	RequestHeaders  map[string]*Header
	RequestBody     []byte
}

func (inst *Request) getHeader(name string, create bool) *Header {
	table := inst.RequestHeaders
	if table == nil {
		table = make(map[string]*Header)
		inst.RequestHeaders = table
	}
	h := table[name]
	if h == nil && create {
		h = new(Header)
		h.Name = name
		table[name] = h
	}
	return h
}

// AddHeader ...
func (inst *Request) AddHeader(name, value string) {
	h := inst.getHeader(name, true)
	h.Add(value)
}

// SetHeader ...
func (inst *Request) SetHeader(name, value string) {
	h := inst.getHeader(name, true)
	h.Set(value)
}

// SetParam ...
func (inst *Request) SetParam(name, value string) {
	table := inst.Params
	if table == nil {
		table = make(map[string]string)
		inst.Params = table
	}
	table[name] = value
}

////////////////////////////////////////////////////////////////////////////////
